package main

import (
	"cms/router"
	service "cms/serivce"
	"context"

	"engine/consts"
	"errors"
	"fmt"
	"github.com/hibiken/asynq"
	"github.com/shopspring/decimal"
	"go.uber.org/zap"
	"lib/config"
	"lib/db"
	"lib/log"
	ratelimit "lib/rate-limit"
	"lib/task"

	"net/http"
	"os"
	"os/signal"
	"syscall"
	"time"
)

// @title			智飞科技平台内部 API
// @version		1.0
// @description	智飞科技平台内部 API 接口文档，包括 代理商、管理后台 以及 供应商的接口。
// @host			api.zhifeiair.com
// @BasePath		/
// @accept			json
// @produce		json
// @schemes		https
func main() {
	decimal.MarshalJSONWithoutQuotes = true

	// 加载配置文件
	err := config.Viper()
	if err != nil {
		panic(err)
	}

	//初始化
	err = log.InitZap(config.GetZapConfig())
	if err != nil {
		panic(err)
	}

	rcf := config.GetRedisConfig()
	err = db.InitRedis(rcf)
	if err != nil {
		panic(err)
	}
	err = db.InitGorm(config.GetMysqlConfig())
	if err != nil {
		panic(err)
	}

	escf := config.GetEsConfig()
	err = db.InitElasticsearch(escf)
	if err != nil {
		panic(err)
	}
	ratelimit.RegisterRedisLimiter(db.GetRedisClient())

	scf := config.GetSystemConfig()
	address := fmt.Sprintf(":%d", scf.Port)

	time.Sleep(10 * time.Microsecond)

	server := http.Server{
		Addr:           address,
		Handler:        router.Routers(),
		ReadTimeout:    120 * time.Second,
		WriteTimeout:   120 * time.Second,
		MaxHeaderBytes: 1 << 20,
	}
	log.Info("Web 服务正常启动", zap.String("address", address))

	go func() {
		if err := server.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
			log.Fatal("Web 服务启动异常: %s" + err.Error())
		}
	}()

	go func() {
		defer func() {
			if err := recover(); err != nil {
				log.Errorf("%v", err)
			}
		}()
		err := StartQueueServer(rcf)
		if err != nil {
			log.Fatalf("启动queue服务失败：%v", err)
		}
	}()

	// 注册关闭处理函数
	quit := make(chan os.Signal, 1)
	signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
	<-quit

	// 优雅地关闭服务器
	fmt.Println("停止 Web 服务...")
	if err := server.Shutdown(context.Background()); err != nil {
		log.Fatal("Web 服务退出异常:" + err.Error())
	}

	fmt.Println("Web 服务正常退出")

}

func StartQueueServer(rcf *config.Redis) error {
	task.InitQueueClient(rcf)
	srv := asynq.NewServer(
		asynq.RedisClientOpt{
			Network:  rcf.Network,
			Addr:     fmt.Sprintf("%s:%s", rcf.Address, rcf.Port),
			Password: rcf.Password,
			DB:       rcf.Database,
		},
		asynq.Config{
			// Specify how many concurrent workers to use
			Concurrency: 1,
			// Optionally specify multiple queues with different priority.
			// See the godoc for other configuration options
		},
	)
	// mux maps a type to a handle
	mux := asynq.NewServeMux()
	// ...register other handlers...
	mux.HandleFunc(string(consts.SendEmail), service.HandleSendEmailTask)
	mux.HandleFunc(string(consts.SyncCoreDataJson), service.HandleUserLevel)
	mux.HandleFunc(string(consts.SyncFlightOrder), service.HandleUserLevelNew)
	mux.HandleFunc(string(consts.SyncFlightOrderData), service.HandleUserLevelNewOrder)
	mux.HandleFunc(string(consts.Xuanshang), service.HandleXuanshangTask)
	mux.HandleFunc(string(consts.Ems), service.HandleEmsTask)
	mux.HandleFunc(string(consts.ZhuShouDea), service.HandleZhunshouTask)
	mux.HandleFunc(string(consts.ZhuShouDeaWw), service.HandleZhunshouTaskWx)
	mux.HandleFunc(string(consts.DingdanLevel), service.HandleDingdanLevelTask)
	mux.HandleFunc(string(consts.DingdanLevelGamesss), service.HandleDingdanLevelTaskGame)
	mux.HandleFunc(string(consts.Chanchu), service.HandleChanChu)
	mux.HandleFunc(string(consts.Fenhong), service.HandleFenhong)
	mux.HandleFunc(string(consts.FenhongFlish), service.HandleFenhongFlish)
	mux.HandleFunc(string(consts.SyncUserAddMoney), service.HandleFenhongAddMoeny)
	//mux.HandleFunc(string(consts.SyncFlightOrderVoyageChange), service.FlightChangeNotify)
	//mux.HandleFunc(string(consts.SyncFlightOrderUnififiNotify), service.UnififiFlightOrderNotify)

	if err := srv.Start(mux); err != nil {
		log.Errorf("could not run server: %v", err)
		return err
	}

	return nil
}
